/*********************************************************************************
 *
 *  DMP - Day Must Play_er
 *  Copyright (c) 2011 Dario Mazza (dariomzz@gmail.com)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3, or (at your option)
 *  any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program (see the file COPYING); if not, see
 *  http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 *
 ********************************************************************************/

#include <QtGui>
#include <sstream>
#include "DMPMainWindow.h"
#include <taglib/fileref.h>
#include <taglib/tag.h>
#include <taglib/mpegfile.h>
#include <taglib/id3v2tag.h>
#include <taglib/attachedpictureframe.h>

DMPMainWindow::DMPMainWindow(QWidget* parent):QMainWindow(parent) {
    	audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
	mediaObject = new Phonon::MediaObject(this);
	metaInformationResolver = new Phonon::MediaObject(this);
	mediaObject->setTickInterval(1000);
    	connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
    	connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
            this, SLOT(stateChanged(Phonon::State, Phonon::State)));
    	connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
            this, SLOT(metaStateChanged(Phonon::State, Phonon::State)));
    	connect(mediaObject, SIGNAL(currentSourceChanged(const Phonon::MediaSource &)),
            this, SLOT(sourceChanged(const Phonon::MediaSource &)));
    	connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
    	Phonon::createPath(mediaObject, audioOutput);
	setupUi(this);
    	seekSlider->setMediaObject(mediaObject);
    	volumeSlider->setAudioOutput(audioOutput);
    	setupActions();
	setupMenus();
	setupToolbar();
	addFiles();	
	this->move(30,50);
	this->time_label->setText("00:00");
}

void DMPMainWindow::about() {
}

void DMPMainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
    switch (newState) {
        case Phonon::ErrorState:
            if (mediaObject->errorType() == Phonon::FatalError) {
                QMessageBox::warning(this, tr("Fatal Error"),
                mediaObject->errorString());
            } else {
                QMessageBox::warning(this, tr("Error"),
                mediaObject->errorString());
            }
            break;
        case Phonon::PlayingState:
                playAction->setEnabled(false);
                pauseAction->setEnabled(true);
                stopAction->setEnabled(true);
                break;
        case Phonon::StoppedState:
                stopAction->setEnabled(false);
                playAction->setEnabled(true);
                pauseAction->setEnabled(false);
               	time_label->setText("00:00");
                break;
        case Phonon::PausedState:
                pauseAction->setEnabled(false);
                stopAction->setEnabled(true);
                playAction->setEnabled(true);
                break;
        case Phonon::BufferingState:
                break;
        default:
		break;
    }
}

void DMPMainWindow::tick(qint64 time) {
    QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60);
    time_label->setText(displayTime.toString("mm:ss"));
}

void DMPMainWindow::sourceChanged(const Phonon::MediaSource &source) {
    //musicTable->selectRow(sources.indexOf(source));
    time_label->setText("00:00");
}

void DMPMainWindow::metaStateChanged(Phonon::State newState, Phonon::State /* oldState */) {
    if (newState == Phonon::ErrorState) {
        QMessageBox::warning(this, tr("Error opening files"),
            metaInformationResolver->errorString());
        while (!sources.isEmpty() &&
               !(sources.takeLast() == metaInformationResolver->currentSource()));
        return;
    }
    if (newState != Phonon::StoppedState && newState != Phonon::PausedState)
        return;
    if (metaInformationResolver->currentSource().type() == Phonon::MediaSource::Invalid)
            return;
    QMap<QString, QString> metaData = metaInformationResolver->metaData();
    TagLib::MPEG::File audioFile(metaInformationResolver->currentSource().fileName().toLatin1().data());
    int time = audioFile.audioProperties()->length();
    QTime displayTime(0, (time / 60) % 60, (time) % 60);
    this->length_label->setText(displayTime.toString("mm:ss"));
    writeMetadataLabel(audioFile);
    /*
    QString title = metaData.value("TITLE");
    if (title == "")
        title = metaInformationResolver->currentSource().fileName();

    QTableWidgetItem *titleItem = new QTableWidgetItem(title);
    titleItem->setFlags(titleItem->flags() ^ Qt::ItemIsEditable);
    QTableWidgetItem *artistItem = new QTableWidgetItem(metaData.value("ARTIST"));
    artistItem->setFlags(artistItem->flags() ^ Qt::ItemIsEditable);
    QTableWidgetItem *albumItem = new QTableWidgetItem(metaData.value("ALBUM"));
    albumItem->setFlags(albumItem->flags() ^ Qt::ItemIsEditable);
    QTableWidgetItem *yearItem = new QTableWidgetItem(metaData.value("DATE"));
    yearItem->setFlags(yearItem->flags() ^ Qt::ItemIsEditable);
    int currentRow = musicTable->rowCount();
    musicTable->insertRow(currentRow);
    musicTable->setItem(currentRow, 0, titleItem);
    musicTable->setItem(currentRow, 1, artistItem);
    musicTable->setItem(currentRow, 2, albumItem);
    musicTable->setItem(currentRow, 3, yearItem);
    */
    //if (musicTable->selectedItems().isEmpty()) {
        //musicTable->selectRow(0);
        mediaObject->setCurrentSource(metaInformationResolver->currentSource());
    //}
    Phonon::MediaSource source = metaInformationResolver->currentSource();
    int index = sources.indexOf(metaInformationResolver->currentSource()) + 1;
    
    if (sources.size() > index) {
        metaInformationResolver->setCurrentSource(sources.at(index));
    }
    else {
        /*musicTable->resizeColumnsToContents();
        if (musicTable->columnWidth(0) > 300)
            musicTable->setColumnWidth(0, 300);*/
    }
}

void DMPMainWindow::writeMetadataLabel(TagLib::MPEG::File& audioFile) {
	TagLib::ID3v2::Tag* tTag=audioFile.ID3v2Tag();
	QString metadata=QString("<big><b>%1</b></big><br/>by <i>%2</i><br/>from <i>%3</i> %4");
	metadata=metadata.arg(tTag->title().toCString(true),tTag->artist().toCString(true),tTag->album().toCString(true));
	if (tTag->year()!=0) {
		metadata=metadata.arg(QString("(%1)").arg(tTag->year()));
	} else {
		metadata=metadata.arg("");
	}
	this->current_metadata_label->setText(metadata);
	unsigned int trackNum=tTag->track();
	this->track_num_label->setText(QString("Track: %1").arg(trackNum));
	QString genreStr=QString("Unknown");
	if (!tTag->genre().isNull()&&!tTag->genre().isEmpty()) {
		genreStr=QString(tTag->genre().toCString(true));
	}
	this->genre_label->setText(QString("Genre: <i>%1</i>").arg(genreStr));
	this->bitrate_label->setText(QString("Bitrate: %1 Kbps").arg(audioFile.audioProperties()->bitrate()));
	TagLib::ID3v2::FrameList fl=tTag->frameList("APIC");
	if (fl.size()>0) {
		TagLib::ID3v2::AttachedPictureFrame* picFrame=static_cast<TagLib::ID3v2::AttachedPictureFrame*>(fl.front());
		QPixmap cover;
		cover.loadFromData((const uchar*)picFrame->picture().data(),picFrame->picture().size());
		this->cover_label->setPixmap(cover);
	}
}

void DMPMainWindow::aboutToFinish() {
    int index = sources.indexOf(mediaObject->currentSource()) + 1;
    if (sources.size() > index) {
        mediaObject->enqueue(sources.at(index));
    }
}

void DMPMainWindow::setupActions() {
    playAction = new QAction(QIcon(QPixmap(QString::fromUtf8(":/resources/playback_play.png"))), tr("Play"), this);
    playAction->setShortcut(tr("C"));
    playAction->setDisabled(true);
    pauseAction = new QAction(QIcon(QPixmap(QString::fromUtf8(":/resources/pause.png"))), tr("Pause"), this);
    pauseAction->setShortcut(tr("X"));
    pauseAction->setDisabled(true);
    stopAction = new QAction(QIcon(QPixmap(QString::fromUtf8(":/resources/playback_stop.png"))), tr("Stop"), this);
    stopAction->setShortcut(tr("V"));
    stopAction->setDisabled(true);
    nextAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipForward), tr("Next"), this);
    nextAction->setShortcut(tr("Ctrl+N"));
    previousAction = new QAction(style()->standardIcon(QStyle::SP_MediaSkipBackward), tr("Previous"), this);
    previousAction->setShortcut(tr("Ctrl+R"));
    /*addFilesAction = new QAction(tr("Add &Files"), this);
    addFilesAction->setShortcut(tr("Ctrl+F"));*/
    exitAction = new QAction(tr("E&xit"), this);
    exitAction->setShortcut(tr("Ctrl+X"));
    aboutAction = new QAction(tr("A&bout"), this);
    aboutAction->setShortcut(tr("Ctrl+B"));
    aboutQtAction = new QAction(tr("About &Qt"), this);
    aboutQtAction->setShortcut(tr("Ctrl+Q"));

    connect(playAction, SIGNAL(triggered()), mediaObject, SLOT(play()));
    connect(pauseAction, SIGNAL(triggered()), mediaObject, SLOT(pause()) );
    connect(stopAction, SIGNAL(triggered()), mediaObject, SLOT(stop()));
    //connect(addFilesAction, SIGNAL(triggered()), this, SLOT(addFiles()));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void DMPMainWindow::setupMenus() {
    QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
    /*fileMenu->addAction(addFilesAction);
    fileMenu->addSeparator();*/
    fileMenu->addAction(exitAction);

    QMenu *aboutMenu = menuBar()->addMenu(tr("&Help"));
    aboutMenu->addAction(aboutAction);
    aboutMenu->addAction(aboutQtAction);
}

void DMPMainWindow::setupToolbar() {
	this->play_button->setDefaultAction(playAction);
	this->pause_button->setDefaultAction(pauseAction);
	this->stop_button->setDefaultAction(stopAction);
}

void DMPMainWindow::addFiles() {
    QStringList files;
    files<<"/home/losciamano/Scaricati/JDownloads/Carl.Orff.Carmina.Burana/Carl Orff - Carmina Burana/01 - O Fortuna.mp3";

    if (files.isEmpty())
        return;

    int index = sources.size();
    foreach (QString string, files) {
        Phonon::MediaSource source(string);
        sources.append(source);
    } 
    if (!sources.isEmpty())
        metaInformationResolver->setCurrentSource(sources.at(index));
}
